﻿#region Using Directives

using System;

#endregion Using Directives

namespace SharePointStu.CAMLHelper.CAML
{
    /// <summary>
    /// Class that defines a <see cref="T:SharePointStu.CAMLHelper.CAML.Query"/> object and where in the overall CAML query
    /// it should be created, based on the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup.MergeTypes"/> enumerator and existing
    /// query nodes.
    /// </summary>
    public class QueryGroup
    {
        #region Public Enums

        /// <summary>
        /// Type of merges available for the <see cref="T:SharePointStu.CAMLHelper.CAML.Query"/> object.
        /// </summary>
        public enum MergeTypes
        {
            /// <summary>
            /// Merge the query into the top group of CAML queries.
            /// </summary>
            TopGroup,
            /// <summary>
            /// Merge the query into the bottom (2nd) group of CAML queries.
            /// </summary>
            BottomGroup,
            /// <summary>
            /// Insert the query so it becomes the parent of the existing query nodes.
            /// </summary>
            Contain
        }

        #endregion Public Enums

        #region Private Members

        readonly Query _query;
        Types.JoinTypes _joinType;
        MergeTypes _mergeType;

        #endregion Private Members

        #region Public Properties

        /// <summary>
        /// Get the <see cref="T:SharePointStu.CAMLHelper.CAML.Query"/> object for this grouping.
        /// </summary>
        internal Query Query
        {
            get { return _query; }
        }

        /// <summary>
        /// Get or set the type of logical join to perform for this query group.
        /// </summary>
        public Types.JoinTypes JoinType
        {
            get { return _joinType; }
            set { _joinType = value; }
        }

        /// <summary>
        /// Get or set the type of merge to perform for this query group when injecting the query into the overall CAML query.
        /// </summary>
        public MergeTypes MergeType
        {
            get { return _mergeType; }
            set { _mergeType = value; }
        }

        #endregion Public Properties

        #region Constructors

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        public QueryGroup()
        {
            this.JoinType = Types.JoinTypes.And;
            this.MergeType = MergeTypes.Contain;
        }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="joinType">The type of logical join to perform with the query.</param>
        /// <param name="mergeType">The merge type of the query.</param>
        public QueryGroup(Types.JoinTypes joinType, MergeTypes mergeType)
        {
            this.JoinType = joinType;
            this.MergeType = mergeType;
        }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        /// <remarks>Applies default values - fieldRefType = Name; joinType = And; mergeType = Contain</remarks>
        public QueryGroup(string field, Types.FieldTypes fieldType, Types.QueryTypes queryType, string value)
            : this(Types.JoinTypes.And, MergeTypes.Contain, Types.FieldRefTypes.Name, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="fieldRefType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object type of the field being queried.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        /// <remarks>Applies default values - joinType = And; mergeType = Contain</remarks>
        public QueryGroup(Types.FieldRefTypes fieldRefType, string field, Types.FieldTypes fieldType,
                                Types.QueryTypes queryType, string value)
            : this(Types.JoinTypes.And, MergeTypes.Contain, fieldRefType, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="joinType">The type of logical join to perform with the query.</param>
        /// <param name="mergeType">The merge type of the query.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        public QueryGroup(Types.JoinTypes joinType, MergeTypes mergeType,
                                string field, Types.FieldTypes fieldType, Types.QueryTypes queryType, string value)
            : this(joinType, mergeType, Types.FieldRefTypes.Name, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="mergeType">The merge type of the query.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        public QueryGroup(MergeTypes mergeType, string field, Types.FieldTypes fieldType, Types.QueryTypes queryType,
                                string value)
            : this(Types.JoinTypes.And, mergeType, Types.FieldRefTypes.Name, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="joinType">The type of logical join to perform with the query.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        public QueryGroup(Types.JoinTypes joinType, string field, Types.FieldTypes fieldType,
                                Types.QueryTypes queryType, string value)
            : this(joinType, MergeTypes.TopGroup, Types.FieldRefTypes.Name, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="mergeType">The merge type of the query.</param>
        /// <param name="fieldRefType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object type of the field being queried.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        public QueryGroup(MergeTypes mergeType, Types.FieldRefTypes fieldRefType, string field, Types.FieldTypes fieldType,
                                Types.QueryTypes queryType, string value)
            : this(Types.JoinTypes.And, mergeType, fieldRefType, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="joinType">The type of logical join to perform with the query.</param>
        /// <param name="fieldRefType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object type of the field being queried.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        public QueryGroup(Types.JoinTypes joinType, Types.FieldRefTypes fieldRefType, string field,
                                Types.FieldTypes fieldType, Types.QueryTypes queryType, string value)
            : this(joinType, MergeTypes.TopGroup, fieldRefType, field, fieldType, queryType, value) { }

        /// <summary>
        /// Initialise the <see cref="T:SharePointStu.CAMLHelper.CAML.QueryGroup"/> object.
        /// </summary>
        /// <param name="joinType">The type of logical join to perform with the query.</param>
        /// <param name="mergeType">The merge type of the query.</param>
        /// <param name="fieldRefType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object type of the field being queried.</param>
        /// <param name="field">The name or id of the field to query against.</param>
        /// <param name="fieldType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldTypes"/> object of the field.</param>
        /// <param name="queryType">The <see cref="T:SharePointStu.CAMLHelper.CAML.Types.FieldRefTypes"/> object that defines the type of query to perform.</param>
        /// <param name="value">The value of the field being queried.</param>
        public QueryGroup(Types.JoinTypes joinType, MergeTypes mergeType,
                                Types.FieldRefTypes fieldRefType, string field, Types.FieldTypes fieldType,
                                Types.QueryTypes queryType, string value)
            : this(joinType, mergeType)
        {
            _query = new Query(field, fieldRefType, fieldType, queryType, value);
        }

        #endregion Constructors
    }
}
